//Interface/käyttöliittymä potentiaali-api:lle., cInfo, metodien toteutus.
//
//Joonas Koskinen
//Pro Gradu Työ
//Jyväskylän Yliopisto
//***********************************************************

#include "cInfo.h"

using namespace std;

//Constructor for cInfo.
cInfo::cInfo() {
	//Insert numerical method pointers to vector
	numerical.push_back(new RKN);
	numerical.push_back(new Euler);
	numerical.push_back(new RK4);
	numerical.push_back(new ImprovedEuler);
	numerical.push_back(new Numerov);
	numerical.push_back(new RKF23);
	numerical.push_back(new RKF45);
	numerical.push_back(new DOPRI);
        numerical.push_back(new NumerovMatrix);
        numerical.push_back(new NumerovMatrixSparse);
        numerical.push_back(new VerletMatrix);

	//Insert potential well pointers to vector
	potential.push_back(new HO);
	potential.push_back(new Sqinf);
	potential.push_back(new Yukawa);
	potential.push_back(new Sqfinite);
	potential.push_back(new Gaussattr);
	potential.push_back(new Sqsemiinf);
	potential.push_back(new Hydrogen);
	potential.push_back(new Coupledsq);
	potential.push_back(new LennardJones);
	potential.push_back(new HOdipole);
	potential.push_back(new Morse);
	potential.push_back(new SqNsFinite);
        potential.push_back(new tripleGaussian);

	//Insert differential equation pointers to vector
	DY.push_back(new cSchrodinger);

	//Set the active potential, -method and -DE here to default zero.
	activepotential=0;
	activemethod=0;
	activeDE=0;

	vector<double> xx;
        setCalcNextEigen(false);
        setSaveImage(false);
	//For all potentials
	for(unsigned int i=0; i<potential.size(); i++) {
		//Calculate potential minimal values
		potential[i]->setPotMin();

		//Do not use filtering.
//		potential[i]->setUsingFilter(false);
	}
        //Setting automatic finder nextnode value to 0.
        for(unsigned int i=0; i<numerical.size(); i++) {
            setNextNode(0);
        }
}

//Destructor for cInfo.
cInfo::~cInfo() {
	for (unsigned int i=0; i<potential.size(); i++)	{
		delete potential[i];
	}
	for (unsigned int i=0; i<numerical.size(); i++) {
		delete numerical[i];
	}
	for (unsigned int i=0; i<DY.size(); i++) {
		delete DY[i];
	}
        
        //delete[] buf;
}

//!Set the depth of the potential.
void cInfo::set_depth(double value) {
	potential[activepotential] -> setDepth(value);
}
//! Return the name of the active potential
string cInfo::get_pot_name() {
	return potential[activepotential]->getName();
}
//! Return the name of the potential #value
string cInfo::get_pot_name(unsigned int value) {
	if (value > get_pot_count()) {return "Value outside range.";}
	else {
          //  cout << "returning potential name in cInfo: " << potential[value]->getName() << endl;
            return potential[value]->getName();
        }
}

//! Return the number of potentials
unsigned int cInfo::get_pot_count() {
	return potential.size();
}

//! Return the number of solvers
string cInfo::get_solver_name() {
	return numerical[activemethod]->getName();
}

//! Return the name of the solver #value
string cInfo::get_solver_name(unsigned int value) {
	if (value > get_solver_count()) {return "Value outside range.";}
	else return numerical[value]->getName();
}

//! Return the number of solvers
unsigned int cInfo::get_solver_count() {
	return numerical.size();
}

//! Set the width of the potential.
//This has only effect on applicable potentials.'
//The potential is set to be symmetric with respect to the origin.
void cInfo::set_width(double value) {
	potential[activepotential]->setWidth(value);
}

//! Set k, the "spring constant".
void cInfo::set_k(double value) {
	potential[activepotential]->set_k(value);
}

//! Set the active potential.
//Setting this value will change the potential you do the calculations in.
void cInfo::set_activePotential(unsigned int value) {
	if (value > potential.size()) {value=0;}
	activepotential = value;
	init();
//	cout << "is using filter = " << isUsingFilter() << endl;
}
//!!!!!!!!!!!!!!!!!!!
//TODO:Siisti metodia
//!!!!!!!!!!!!!!!!!!!
//! Initialize variables for the active numerical method
void cInfo::init() {
//	vector<double> fxx, txx, tyy,fyy,tdyy,fdyy;
//	double step = numerical[activemethod]->getStep();
//	double nstep = -1.0*step;

	numerical[activemethod]->set_ivaluefx(potential[activepotential]->getFx());
	numerical[activemethod]->set_ivaluetx(potential[activepotential]->getTx());

	numerical[activemethod]->set_fx(potential[activepotential]->getFx());
	numerical[activemethod]->set_tx(potential[activepotential]->getTx());
	numerical[activemethod]->initAttribs(potential[activepotential], DY[activeDE]);

//	cout << "setting secondary initial values" << endl;
////	Second initial values for the methods that need them are calculated using RKN.
//	fxx.push_back(numerical[activemethod]->get_ivaluefx());
//	txx.push_back(numerical[activemethod]->get_ivaluetx());
//	fyy.push_back(numerical[activemethod]->get_ivaluey());
//	tyy.push_back(numerical[activemethod]->get_ivaluey());
//	fdyy.push_back(numerical[activemethod]->get_ivaluefdy());
//	tdyy.push_back(numerical[activemethod]->get_ivaluetdy());

//	cout << "RKN step" << endl;
//        
//  //      Use RKN to calculate second step
//        
//            numerical[0]->method_step(step, txx, tyy, tdyy, DY[activeDE], potential[activepotential]);
//            numerical[0]->method_step(nstep, fxx, fyy, fdyy, DY[activeDE], potential[activepotential]);
//        
//        cout << "inserting..." << endl;
//	//Insert second initial values to vectors.
//	numerical[activemethod]->set_ivaluetx2(txx.back());
//	numerical[activemethod]->set_ivaluefx2(fxx.back());
//	numerical[activemethod]->set_ivaluety2(tyy.back());
//	numerical[activemethod]->set_ivaluefy2(fyy.back());
//	numerical[activemethod]->set_ivaluetdy2(tdyy.back());
//	numerical[activemethod]->set_ivaluefdy2(fdyy.back());
//	cout << "DONE..." << endl;
}

//! Return depth of the potential.
double cInfo::get_depth() {
	return potential[activepotential] -> getDepth();
}

//! Return the width of the potential.
double cInfo::get_width() {
	return potential[activepotential] -> getWidth();
}

//! Return k, the "spring constant" of the potential.
double cInfo::get_k() {
	return potential[activepotential] -> get_k();
}

//! Returns the index of the active potential.
unsigned int cInfo::get_activePotential() {
	return activepotential;
}

//! Set the tolerance
void cInfo::set_f_e_tol(double value) {
	numerical[activemethod]->set_f_e_tol(value);
}

//! Return the tolerance
double cInfo::get_f_e_tol() {
	return numerical[activemethod]->get_f_e_tol();
}

//cDY methods---------------------------

//! Set the energy value.
void cInfo::set_E(double value) {
    //cout << "Energy is " << value << endl;
	DY[activeDE] -> set_E(value);
}

//! Return the energy value.
double cInfo::get_E() {
    return DY[activeDE] -> get_E();
}

//! Return the name of the active differential equation
string cInfo::get_DE_name() {
	return DY[activeDE]->get_name();
}

//! Return the number of available differential equations.
unsigned int cInfo::get_DE_count() {
	return DY.size();
}

//! Set the active differential equation.
void cInfo::set_activeDE(unsigned int value){
	if (value > get_DE_count()) {value = 0;}
	activeDE=value;
	init();
}

//! Return the index of the currently active DE.
int cInfo::get_activeDE()
{
	return activeDE;
}

//-----------------------------------------

//! Set the step size for the numerical integrator.
void cInfo::set_step(double value){
	numerical[activemethod]->setStep(value);
}

//! Finds the next eigenfunction starting from the given energy.
//Note that this method does not guarantee that the eigenfunction
//that is found is really the next eigenfunction for the eigenenergy E_{n+/-1}.
//It may be a higher or a lower state.
//You can search for the previous or the next eigen energy by giving
//a negative or positive energy stepsize (E_step) respectivly.
void cInfo::find_next_eigenfunction(double E_step, unsigned int break_value) {
    init();
    try {
        numerical[activemethod]->findNextEigenfunction(DY[activeDE], potential[activepotential], break_value);
    }
    catch(cNumericalError &ne) {
        numerical[activemethod]->clearAllVectors();
    }
	
}

//! Sets the active numerical method.
//It is never undefined.  It will default to 0.
void cInfo::set_activeMethod(unsigned int value) {
	if (value > get_solver_count()) {value=0;}
        //Reset the old method and clear vectors.
        numerical[activemethod]->initAttribs(potential[activepotential], DY[activeDE]);
	//set new active method
        activemethod=value;
	init();
}

//! Returns the index of the active numerical method
unsigned int cInfo::get_activeMethod() {
	return activemethod;
}

//! calls the active numerical method and calculates the
//! solution for the given energy, potential and DE.  This method does not
//! guarantee, that the solution plotted is a plot of an eigenfunction.
void cInfo::calculate() {
	init();
	try {
            if(isCalcNextEigen()==true && numerical[activemethod]->isMatrixMethod() == false) {
                numerical[activemethod]->findNextEigenfunction(DY[activeDE], potential[activepotential], 10000);
            }
            if(numerical[activemethod]->isMatrixMethod() == true) {
                numerical[activemethod]->methodMatrix(DY[activeDE],potential[activepotential]);
            }
            else {
		numerical[activemethod]->method(DY[activeDE], potential[activepotential]);
            }
	}
	catch (cNumericalError &ne) {
            numerical[activemethod]->clearAllVectors();
            cout << "Method died..." << endl;
	}
}

void cInfo::setEigenIndex(int eigenIndex){
    numerical[activemethod]->setEigenIndex(eigenIndex);
}

int cInfo::getEigenIndex() const {
    return numerical[activemethod]->getEigenIndex();
}

double cInfo::getEigenValue(int n) {
    DY[activeDE]->set_E(numerical[activemethod]->getEigenValue(n));
    return numerical[activemethod]->getEigenValue(n);
}

void cInfo::getEigenVector(int n) {
    numerical[activemethod]->getEigenVector(n);
}

void cInfo::setSaveImage(bool saveImage) {
    this->saveImage = saveImage;
}

bool cInfo::isSaveImage() const {
    return saveImage;
}

//! Return vector x
vector<double> cInfo::get_x() {
	return numerical[activemethod]->get_x();
}
//! Return vector y
vector<double> cInfo::get_y() {
	return numerical[activemethod]->get_y();
}

//! Return potential minimal energy
double cInfo::get_min_energy() {
	return potential[activepotential]->getMinEnergy();
}

//! Write vector arr to a file filename.
void cInfo::write_disk(string filename, vector<double> arr) {
	string* s = new string[arr.size()];
	cLevy writer;
	for (unsigned int i=0; i<arr.size(); i++) {
		s[i]=tostring(arr[i]);
	}
	writer.writeArrayToFile(filename, s, arr.size()-1);
}
void cInfo::appendToFile(string filename, string value) {
    cLevy writer;
    writer.appendToFile(filename, value);
}

//! Set the size of the universe.
void cInfo::set_universe(double value)
{
	if (value <= 0) {value = 10;}
	potential[activepotential]->setUniverse(value);
}

//! Writes the contents of the given vectors in a way that gnuplot can understand and plot.
//It does not include any gnuplot specific controls so
//you can plot the data in any plotter program where you can specify
//the delimiter character.
void cInfo::write_gnuplot_file(string filename, vector<double> x, vector<double> y) {
	string* s = new string[x.size()];
	cLevy writer;
	for (unsigned int i=0; i<x.size(); i++) {
		s[i]=tostring(x[i]);
		s[i]+=" ";
		s[i]+=tostring(y[i]);
	}
	writer.writeArrayToFile(filename, s, x.size()-1);
}

//! Returns the number of zeros (nodes) found from the solution vector
int cInfo::find_zeros() {
	return numerical[activemethod]->findZeros();
}

//! Set the value of the left edge of the potential along x-axis
void cInfo::set_pot_left(double value) {
	potential[activepotential]->setPotLeft(value);
}

//! Set the value of the right edge of the potential along the x-axis
void cInfo::set_pot_right(double value) {
	potential[activepotential]->setPotRight(value);
}

//! Return the x-coordinate of the left edge of the potential
double cInfo::get_pot_left() {
	return potential[activepotential]->getPotLeft();
}

//! Return the x-coordinate of the right edge of the potential
double cInfo::get_pot_right() {
	return potential[activepotential]->getPotRight();
}

//! Moves the potential along the x-axis.
//This is accomplished by adding 'value' to
//potential->pot_left and potential->pot_right
//This method does not alter potential width.
void cInfo::move_potential(double value) {
	potential[activepotential]->setPotLeft(potential[activepotential]->getPotLeft()+value);
	potential[activepotential]->setPotRight(potential[activepotential]->getPotRight()+value);
}

//TODO:  Kirjoita kuvailukommentti.  Tee bool-tyyppinen muuttuja ja if-lause, jolla määrätään näytetäänkö
//graafi ruudulla gnuplotilla vai ei.(showonscreen())
void cInfo::gp_plotxy(vector<double> x, vector<double> y, string title, string style, string labelx, string labely, string filename, string terminal){
	if(title.empty()) {title = get_pot_name();}
	if(style.empty()) {style = "points";}
	if(labelx.empty()){labelx = "pos";}  
	if(labely.empty()){labely = "Energy";}
	string cmd_terminal = "set terminal " + terminal;
	string cmd_output = "set output '" + filename + "'";
	//gp.set_title(title);
	//gp.set_style(style);
	//gp.set_xlabel(labelx);
	//gp.set_ylabel(labely);
	//gp.cmd(cmd_terminal);
	//gp.cmd(cmd_output);
	//Copy elements from vector<double> to vector<double>
	vector<double> doublex(x.begin(),x.end());
	vector<double> doubley(y.begin(),y.end());
//	gp.savetopng("eigen");
	//	gp.savetops("testps");
//	gp.plotfile_xy("data",title);
	//gp.showonscreen();

}

//! Takes step size as an argument and set the output to reference-vectors &x, &y.
//If filtering is enabled use filtered potential output.
//This is done so that (x{i},y{j}) i={0,2,4,6,...}, j={1,3,5,...}
//This vector contains the graph of the potential function
void cInfo::get_potential_form(vector<double> &x, vector<double> &y,double step) {
	if(step <= 0) step=0.1;
//	if(isUsingFilter()==false){
		double loc = potential[activepotential]->getUniverseLeft(); //getPotLeft();
		while(loc <= potential[activepotential]->getUniverseRight()) {  //getPotRight()) {
			y.push_back(potential[activepotential]->potential(loc));
			x.push_back(loc);
			loc = loc+step;
//		}
	}
//	else if(isUsingFilter()==true){
//		y = potential[activepotential]->getFilterOutput();
//		for(unsigned int i=0; i<y.size(); i++) {
//			x.push_back( potential[activepotential]->get_pot_left() + i * potential[activepotential]->getFilterStep());
//		}
//	}
}

//! Return the i:th element of the vector x.
double cInfo::get_xi(unsigned int i) {
	return numerical[activemethod]->get_xi(i);
}

//! Return the i:th elementh of the vector y.
double cInfo::get_yi(unsigned int i) {
	return numerical[activemethod]->get_yi(i);
}

//! Return the size of the vector x.
unsigned int cInfo::sizeof_x() {
	return numerical[activemethod]->sizeof_x();
}

//! Return the size of the vector y.
unsigned int cInfo::sizeof_y() {
	return numerical[activemethod]->sizeof_y();
}

//! Return the depth of the active potential at x
double cInfo::get_poty(double x) {
	return potential[activepotential]->potential(x);
}

//! Set the quantum number l.
void cInfo::set_l(unsigned int value) {
	potential[activepotential]->set_l(value);
}

//! Get the quantum number l.
unsigned int cInfo::get_l(void) {
	return potential[activepotential]->get_l();
}


//double cInfo::getFilterStep() const
//{
//	return potential[activepotential]->getFilterStep();
//}
//
//bool cInfo::isUsingFilter() const
//{
//	return potential[activepotential]->isUsingFilter();
//}
//
//vector<double> cInfo::getFilterData() const
//{
//	return potential[activepotential]->getFilterOutput();
//}
//
//
//void cInfo::setFilterStep(double value)
//{
//	potential[activepotential]->setFilterStep(value);
//}
//
//void cInfo::setUsingFilter(bool value)
//{
//	potential[activepotential]->setUsingFilter(value);
//}

double cInfo::getResultLimit(){
	return numerical[activemethod]->getResultLimit();
}

void cInfo::setResultLimit(double value){
	numerical[activemethod]->setResultLimit(value);
}

unsigned int cInfo::getLimitIndexBegin(){
	return numerical[activemethod]->getLimitIndexBegin();
}

unsigned int cInfo::getLimitIndexEnd(){
	return numerical[activemethod]->getLimitIndexEnd();
}

void cInfo::limitResultVector(){
	numerical[activemethod]->limitResultVector();
}
void cInfo::setCalcNextEigen(bool calcNextEigen) {
    this->calcNextEigen = calcNextEigen;
}
bool cInfo::isCalcNextEigen() const {
    return calcNextEigen;
}

void cInfo::useResultLimit(bool value){
	numerical[activemethod]->useResultLimit(value);
}

bool cInfo::isResultLimitSet(){
	return numerical[activemethod]->isResultLimitSet();
}

void cInfo::setNextNode(unsigned int value) {
    numerical[activemethod]->setNextNode(value);
}

unsigned int cInfo::getNextNode() {
   return numerical[activemethod]->getNextNode();
}

double cInfo::getE_step() {
    return numerical[activemethod]->getE_step();
}

void cInfo::setE_step(double value) {
    numerical[activemethod]->setE_step(value);
}

void cInfo::plotPotential(int width, int height) {
    vector<double> px,py;
    px.clear();
    py.clear();
    potGraph.Clf();
    get_potential_form(px,py,0.01);
    potDataX.Set(px);
    potDataY.Set(py);
    
    potGraph.Alpha(true);
    potGraph.SetRanges(potDataX.Minimal(),potDataX.Maximal(),potDataY.Minimal(),potDataY.Maximal());
    //std::cout << px[0] << " " << px.back() << std::endl;
    //std::cout << py[0] << " " << py.back() << std::endl;
    potGraph.SetFontSizePT(5);
    potGraph.SetPalette("b0");
    potGraph.SetSize(width,height);
    potGraph.SubPlot(1,1,0,"");
    potGraph.SetRotatedText(false);
    potGraph.Axis("xyU");
    potGraph.Label('x',"x");
    potGraph.Label('y',"V");
    
    potGraph.Plot(potDataX,potDataY);
    potGraph.WriteFrame("/tmp/pot_test.png");
    
}

void cInfo::plotSolutionAndPotential(int width, int height) {
    //useResultLimit(true);
    useResultLimit(false);
    setResultLimit(10e-6);
    limitResultVector();
    std::string title, iFilename, path;
    const char *c_filename;
    
    path = "/home/murmeli/Gradu/results/img/";
    
    iFilename = path + get_solver_name() + "_" + get_pot_name() + "_E" + tostring(get_E()) + "step" + tostring(getStep()) + ".png"; 
    c_filename = iFilename.c_str();
    
    //---------------------------------------------------
    vector<double> px,py,yy;
    px.clear();
    py.clear();
    yy = get_y();
    solpotGraph.Clf();
    get_potential_form(px,py,getStep());
    potDataX.Set(px);
    potDataY.Set(py);
    solDataX.Set(get_x());
    transform(yy.begin(), yy.end(), yy.begin(),bind2nd(std::plus<double>(),get_E()));
    solDataY.Set(yy);
    
    solpotGraph.Alpha(true);
    //solpotGraph.SetRanges((get_x())[getLimitIndexBegin()],(get_x())[getLimitIndexEnd()],(*min_element(py.begin(), py.end()))-0.25 ,5.0);
    solpotGraph.SetRanges(get_pot_left(),get_pot_right(),(*min_element(py.begin(), py.end()))-0.25 ,0.50);
    solpotGraph.SetFontSizePT(5);
    solpotGraph.SetPalette("Hr");
    solpotGraph.SetSize(width,height);
    solpotGraph.SubPlot(1,1,0,"");
    solpotGraph.SetRotatedText(false);
    solpotGraph.Axis("xyU");
    solpotGraph.Label('x',"x");
    solpotGraph.Label('y',"V");
    
    solpotGraph.Plot(potDataX,potDataY, "H");
    solpotGraph.Plot(solDataX,solDataY,"r");
    solpotGraph.WriteFrame(c_filename);
  
}

void cInfo::plotMultiple(int width, int height, vector<int> n, bool displayAxis) {
    useResultLimit(false);
    setResultLimit(10e-6);
    limitResultVector();
    std::string title, iFilename, path;
    const char *c_filename;
    path = "/home/murmeli/Gradu/results/img/";
    
    iFilename = path + get_solver_name() + "_" + get_pot_name() + "_E" + tostring(get_E()) + "step" + tostring(getStep()) + ".png"; 
    c_filename = iFilename.c_str();
    
    vector<double> px,py,yy;
    px.clear();
    py.clear();
    solpotGraph.Clf();
    get_potential_form(px,py,getStep());
    potDataX.Set(px);
    potDataY.Set(py);
    solDataX.Set(get_x());
    
    solpotGraph.Alpha(true);
    //solpotGraph.SetRanges(get_pot_left(),get_pot_right(),(*min_element(py.begin(), py.end()))-0.25 ,getEigenValue(n.back()) + 1.50);
    solpotGraph.SetRanges(get_x()[0],get_x().back(),(*min_element(py.begin(), py.end()))-0.25 ,getEigenValue(n.back()) + 1.50);
    solpotGraph.SetFontSizePT(5);
    solpotGraph.SetPalette("Hr");
    solpotGraph.SetSize(width,height);
    solpotGraph.SubPlot(1,1,0,"");
    solpotGraph.SetRotatedText(false);
    
    if(displayAxis == true) {
        solpotGraph.Axis("xyU");
        solpotGraph.Label('x',"x");
        solpotGraph.Label('y',"V");
    }
    
    solpotGraph.Plot(potDataX,potDataY, "H");
    
    for(int i = 0; i < n.size(); i++) {
        //getEigenValue(i);
        getEigenVector(n[i]);
        yy = get_y();
        transform(yy.begin(), yy.end(), yy.begin(),bind2nd(std::plus<double>(),getEigenValue(n[i])));
        solDataY.Set(yy);
        solpotGraph.Plot(solDataX,solDataY,"r");
    }
    solpotGraph.WriteFrame(c_filename);
  
}

double cInfo::getStep() {
    return numerical[activemethod]->getStep();
}

void cInfo::plotSolution(int width, int height) {
    useResultLimit(true);
    //useResultLimit(false);
    setResultLimit(10e-6);
    limitResultVector();
    std::string title, iFilename, /*rFilename, resultString, */path /*,delim*/;
    const char /** c_title,*/ * c_filename;
    
    path = "/home/murmeli/Gradu/results/";
    //delim = " | ";
    //title = get_pot_name() + " " + tostring(get_E());
    //c_title = title.c_str();
    
    iFilename = path + get_solver_name() + "_" + get_pot_name() + "_E" + tostring(get_E()) + "step" + tostring(getStep()) + ".png"; 
    c_filename = iFilename.c_str();
    
    //resultString = get_solver_name() + delim + tostring(getStep()) + delim + get_pot_name() + delim + tostring(get_E());
    
    //rFilename = path + "results.txt";
    
    solGraph.Clf();
    solDataX.Set(get_x());
    solDataY.Set(get_y());
    solGraph.Alpha(true);
    //cout << (get_x()).size() << "  " << (get_y()).size() << endl;
   // cout << "x = " << (get_x())[getLimitIndexBegin()] << " , " << (get_x())[getLimitIndexEnd()] << endl;
   // cout << "limitindex = " << getLimitIndexBegin() << " , " << getLimitIndexEnd() << endl;
    solGraph.SetRanges((get_x())[getLimitIndexBegin()],(get_x())[getLimitIndexEnd()],-1.0,1.0);
    //solGraph.SetRanges(-15,15,-1.0,1.0);
    solGraph.SetFontSizePT(5);
    solGraph.SetPalette("b0");
    solGraph.SetSize(width,height);
    solGraph.SubPlot(1,1,0,"");
    solGraph.SetRotatedText(false);
    solGraph.Axis("xyU");
    solGraph.Label('x',"x");
    solGraph.Label('y',"E");
    //solGraph.Title(c_title);
    //solGraph.SetFontSizePT(6);
    solGraph.Plot(solDataX,solDataY);
    if(isSaveImage()) {
        std::cout << c_filename << endl;
        solGraph.WriteFrame(c_filename);
        //appendToFile(rFilename, resultString);
        writeResults();
    }
}

void cInfo::writeResults() {
    std::string rFilename, resultString, path, delim;
    
    path = "/home/murmeli/Gradu/results/";
    delim = " | ";
        
    resultString = get_solver_name() + delim + tostring(getStep()) + delim + get_pot_name() + delim + tostring(get_E());
    
    rFilename = path + "results.txt";
    appendToFile(rFilename, resultString);
}

void cInfo::getPotentialPlotQt(unsigned char*& pot_buf) {
    int w = potGraph.GetWidth();
    int h = potGraph.GetHeight();
    
    pot_buf = new unsigned char[4*h*w];
    potGraph.GetBGRN(pot_buf, 4*w*h);
}

void cInfo::getSolutionPlotQt(unsigned char * & sol_buf) {
   
    int w = solGraph.GetWidth();
    int h = solGraph.GetHeight();
    
    sol_buf = new unsigned char [4*w*h];
    solGraph.GetBGRN(sol_buf, 4*w*h);
}

int cInfo::getSolutionPlotHeight() {
    return solGraph.GetHeight();
}

int cInfo::getSolutionPlotWidth() {
    return solGraph.GetWidth();
}

int cInfo::getPotentialPlotHeight() {
    return potGraph.GetHeight();
}

int cInfo::getPotentialPlotWidth() {
    return potGraph.GetWidth();
}
